home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Storage / Bento / FileCtr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-22  |  14.7 KB  |  488 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        FileCtr.cpp
  3.  
  4.     Contains:    Implementation of ODFileContainer class.
  5.  
  6.     Owned by:    Vincent Lo
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     1/15/96    TJ        Cleaned Up
  13.         <23>    10/24/95    jpa        1293441: DM/VL: Bento memory reserve &
  14.                                     fatal container err.
  15.         <22>     10/8/95    TJ        Fixes Recomended by Refball
  16.         <21>     8/24/95    EL        1276818: move Bento container suite
  17.                                     property to BentoDef.h
  18.         <20>     8/12/95    TÇ        1276806 Optimization: use kODFalse instead
  19.                                     of kODTrue in comparisons
  20.         <19>      8/3/95    RR        #1257260: Collapse B classes. Remove
  21.                                     somInit methods. Don't call IsInitialized
  22.                                     or SubclassResponsibility
  23.         <18>     7/21/95    VL        1270320: Create ba on stack in GetID.
  24.         <17>     5/26/95    VL        1251403: Multithreading naming support.
  25.         <16>     5/25/95    jpa        Fixed usage of ODDebug. [1253321]
  26.         <15>     4/25/95    VL        1240737: Make sure that the returned ID
  27.                                     from GetID is set to the right _length.
  28.         <14>     4/15/95    VL        1240014: Modifiy id->_length in
  29.                                     InitContainer to reflect the real length.
  30.         <13>      4/7/95    EL        1225905: Do SetModDate here rather than in
  31.                                     handler.
  32.         <12>     3/24/95    EL        1209355: open container r/w instead of
  33.                                     update because CMTakeSnapShot does not work
  34.                                     with update yet.
  35.         <11>     3/23/95    VL        1230357: Implemented Purge.
  36.         <10>      3/6/95    EL        1225905: Call RestoreModDate if file
  37.                                     container to be aborted.
  38.          <9>     2/21/95    EL        1182275: Garbage collect embedded values
  39.                                     with zero length.
  40.          <8>     2/10/95    VL        1205627: Check to see if a file is locked.
  41.                                     If so, open it read-only.
  42.          <7>    11/14/94    VL        1188257: Use Bento errors in BenotDef.h.
  43.          <6>     11/1/94    VL        1185688: Added SOM_CATCH.
  44.          <5>     9/23/94    VL        1184272: ContainerID is now a sequence of
  45.                                     octets. 1184166: Implemented GetName and
  46.                                     SetName.
  47.          <4>     8/26/94    EL        #1182275 Include code (not yet active) for
  48.                                     merging of container.
  49.          <3>      8/5/94    VL        1171603: Use somSelf->GetCMSession instead
  50.                                     of depending on ODStorageSystem.
  51.          <2>      8/3/94    VL        1153123: Storage to ODStor.
  52.          <1>     6/30/94    CC        first checked in
  53.          <0>     6/28/94    SV        SOMverted
  54.          <2>     4/13/94    VL        1157028: StorageM.h does not include
  55.                                     CMAPI.h anymore, so GetCMSession returns
  56.                                     ODULong.
  57.          <1>     3/24/94    VL        first checked in
  58.         <15>      2/8/94    VL        Use new exception macros.
  59.         <14>     1/21/94    CG        Added include for BentoCtr.h.
  60.         <13>     1/19/94    EL        Use kCMNextGeneration when opening new
  61.                                     container for update.
  62.         <12>     1/12/94    VL        Init changes.
  63.         <11>      1/6/94    EL        Reuse free space in the file.
  64.         <10>     12/3/93    TÇ        Stop including ODError.h, it is included
  65.                                     as ErrorDef.h inside Except.h
  66.          <9>    11/23/93    VL        Made FileContainer pool-aware.
  67.          <8>      9/9/93    VL        Moved Session Global code to ODDraft.
  68.          <7>      8/9/93    VL        Moved error code to ODError.h.
  69.          <6>      8/6/93    VL        fContainer is now fCMContainer and is
  70.                                     protected.
  71.          <5>     6/30/93    VL        Typecasted ODType to CMGlobalName for CM
  72.                                     calls.
  73.          <4>     6/22/93    VL        Used RefCount from ODRefCntObject.
  74.          <3>     6/15/93    VL        This class is now a subclass of
  75.                                     ODBentoContainer. Stripped some code and
  76.                                     put it in ODBentoContainer.
  77.          <2>      6/1/93    VL        Delete fID (PlatformFile object) in the
  78.                                     destructor. Open should SetMetaHandlers to
  79.                                     target and use CMOpenNewContainer instead
  80.                                     of CMOpenContainer.
  81.          <1>     5/27/93    VL        first checked in
  82.         
  83. */
  84.  
  85. #define ODFileContainer_Class_Source
  86.  
  87. #define VARIABLE_MACROS
  88.  
  89. #include <FileCtr.xih>
  90.  
  91. #ifndef _PLFMDEF_
  92. #include "PlfmDef.h"
  93. #endif
  94.  
  95. #ifndef _BENTODEF_
  96. #include "BentoDef.h"
  97. #endif
  98.  
  99. #ifndef SOM_ODStorageSystem_xh
  100. #include <ODStor.xh>
  101. #endif
  102.  
  103. #ifndef _FSHDR_
  104. #include "FSHdr.h"
  105. #endif
  106.  
  107. #ifndef _TARGTHDR_
  108. #include "TargtHdr.h"
  109. #endif
  110.  
  111. #ifndef _INDHDR_
  112. #include "IndHdr.h"
  113. #endif
  114.  
  115. #ifndef __CM_API__
  116. #include "CMAPI.h"
  117. #endif
  118.  
  119. #ifndef _EXCEPT_
  120. #include "Except.h"
  121. #endif
  122.  
  123. #ifndef SOM_Module_OpenDoc_Errors_defined
  124. #include "ErrorDef.xh"
  125. #endif
  126.  
  127. #ifndef _ODNEW_
  128. #include <ODNew.h>
  129. #endif
  130.  
  131. #ifndef _PLFMFILE_
  132. #include <PlfmFile.h>
  133. #endif
  134.  
  135. #ifndef _ITEXT_
  136. #include <IText.h>
  137. #endif
  138.  
  139. #ifndef _BARRAY_
  140. #include <BArray.h>
  141. #endif
  142.  
  143. #ifndef __ALIASES__
  144. #include <Aliases.h>
  145. #endif
  146.  
  147. #ifdef DebugRefCount
  148. #include "Stdio.h"
  149. #endif
  150.  
  151. #if ODDebug
  152. // #define ODDebug_ODFileContainer 1
  153. #endif
  154.  
  155. #pragma segment ODFileContainer
  156.  
  157. //==============================================================================
  158. // ODFileContainer
  159. //==============================================================================
  160.  
  161. //------------------------------------------------------------------------------
  162. // ODFileContainer: ~ODFileContainer
  163. //------------------------------------------------------------------------------
  164.  
  165. SOM_Scope void  SOMLINK ODFileContainersomUninit(ODFileContainer *somSelf)
  166. {
  167.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  168.     ODFileContainerMethodDebug("ODFileContainer","somUninit");
  169.  
  170. #ifdef DebugRefCount
  171.     printf("~ODFileContainer %x CMContainer %x RefCount %d\n", somSelf, _fCMContainer, _fRefCount);
  172.     fflush(stdout);
  173. #endif
  174.  
  175.     TRY{
  176.         Environment *ev = somGetGlobalEnvironment ();
  177.     
  178.         if (_fCMContainer != kODNULL)
  179.             somSelf->Close(ev);
  180.     
  181.         if (_fHandlers != kODNULL)
  182.             delete _fHandlers;
  183.     
  184.         if (_fPlatformFile != kODNULL)
  185.             delete _fPlatformFile;
  186.             
  187.         if (_fAlias != kODNULL)
  188.             ODDisposeHandle((ODHandle) _fAlias);
  189.     }CATCH_ALL{
  190.         // Ignore exceptions
  191.     }ENDTRY
  192. }
  193.  
  194. //------------------------------------------------------------------------------
  195. // ODFileContainer: InitContainer
  196. //------------------------------------------------------------------------------
  197.  
  198. SOM_Scope void  SOMLINK ODFileContainerInitContainer(ODFileContainer *somSelf, Environment *ev,
  199.         ODStorageSystem* storage, ODContainerID* id)
  200. {
  201.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  202.     ODFileContainerMethodDebug("ODFileContainer","InitContainer");
  203.     
  204.     SOM_CATCH return;
  205.  
  206.     /* Moved from somInit. SOM itself sets fields to zero
  207.     _fCMContainer = kODNULL;
  208.     _fHandlers = kODNULL;
  209.     _fAlias = kODNULL;
  210.     _fPlatformFile = kODNULL;
  211.     */
  212.     
  213.     OSErr err = NewAlias(kODNULL, (FSSpec*) id->_buffer, &_fAlias);
  214.     if (err != noErr)
  215.         THROW(kODErrCannotCreateContainer);
  216.  
  217.     // Change id to exclude any garbage before FSSpec.name.
  218.     // struct FSSpec {
  219.     //     short                            vRefNum;
  220.     //     long                            parID;
  221.     //     Str63                            name;
  222.     // };
  223.     id->_length = sizeof(short) + sizeof(long) + ((FSSpec*) id->_buffer)->name[0] + 1;
  224.     
  225.     // Call parent with the updated id
  226.     parent_InitContainer(somSelf, ev, storage, id);
  227.     
  228.     _fPlatformFile = new PlatformFile();
  229.     _fPlatformFile->Specify((ODFileSpec*) id->_buffer);
  230.         
  231.     _fHandlers = new(somSelf->GetHeap(ev)) ODFSBentoHandlers(somSelf->GetCMSession(ev),
  232.                                                             _fPlatformFile);
  233.     _fHandlers->Initialize();
  234. }
  235.  
  236. //------------------------------------------------------------------------------
  237. // ODFileContainer: GetID
  238. //------------------------------------------------------------------------------
  239.  
  240. SOM_Scope ODContainerID  SOMLINK ODFileContainerGetID(ODFileContainer *somSelf, Environment *ev)
  241. {
  242.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  243.     ODFileContainerMethodDebug("ODFileContainer","GetName");
  244.     
  245.     ODByteArray ba;
  246.  
  247.     SOM_TRY
  248.     
  249.     ODBoolean    dummyWasChanged;
  250.     ODFileSpec*    fsSpec = (ODFileSpec*) ODNewPtrClear(sizeof(ODFileSpec));
  251.     
  252.     OSErr err = ResolveAlias(kODNULL, _fAlias, fsSpec, &dummyWasChanged);
  253.     if (err != noErr) {
  254.         *fsSpec = _fPlatformFile->GetFileSpec();
  255.     }
  256.     ba._buffer = (octet*) fsSpec;
  257.     ba._maximum = sizeof(ODFileSpec);
  258.     ba._length = sizeof(short) + sizeof(long) + ((FSSpec*) ba._buffer)->name[0] + 1;
  259.     
  260.     SOM_CATCH_ALL
  261.         ba._buffer = kODNULL;
  262.         ba._maximum = ba._length = 0;
  263.     SOM_ENDTRY
  264.     
  265.     return ba;
  266. }
  267.  
  268. //------------------------------------------------------------------------------
  269. // ODFileContainer: GetName
  270. //------------------------------------------------------------------------------
  271.  
  272. SOM_Scope ODContainerName  SOMLINK ODFileContainerGetName(ODFileContainer *somSelf, Environment *ev)
  273. {
  274.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  275.     ODFileContainerMethodDebug("ODFileContainer","GetName");
  276.  
  277.     ODFileSpec            fsSpec;
  278.     ODContainerName*    name = kODNULL;
  279.     ODBoolean            dummyWasChanged;
  280.     
  281.     SOM_TRY
  282.     
  283.     OSErr err = ResolveAlias(kODNULL, _fAlias, &fsSpec, &dummyWasChanged);
  284.     if (err != noErr) {
  285.         name = _fPlatformFile->GetName();
  286.     }
  287.     else {
  288.         name = CreateIText(0, 0, (StringPtr) &fsSpec.name);
  289.     }
  290.     
  291.     SOM_CATCH_ALL
  292.     SOM_ENDTRY
  293.     
  294.     return *name;    
  295. }
  296.  
  297. //------------------------------------------------------------------------------
  298. // ODFileContainer: SetName
  299. //------------------------------------------------------------------------------
  300.  
  301. SOM_Scope void  SOMLINK ODFileContainerSetName(ODFileContainer *somSelf, Environment *ev,
  302.         ODContainerName* name)
  303. {
  304.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  305.     ODFileContainerMethodDebug("ODFileContainer","SetName");
  306.  
  307.     SOM_CATCH return;
  308.     
  309.     StringPtr fileName = GetPStringFromIText(name);
  310.     _fPlatformFile->Rename(fileName);
  311. }
  312.  
  313. //------------------------------------------------------------------------------
  314. // ODFileContainer: Create
  315. //------------------------------------------------------------------------------
  316.  
  317. SOM_Scope ODContainer*  SOMLINK ODFileContainerCreate(ODFileContainer *somSelf, Environment *ev)
  318. {
  319.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  320.     ODFileContainerMethodDebug("ODFileContainer","Create");
  321.  
  322.     SOM_CATCH return somSelf;
  323.  
  324.     if (_fCMContainer == kODNULL) {
  325.     
  326.         somSelf->SetModDate(ev, _fPlatformFile->GetFileModDate());
  327.  
  328.         CMSession cmSession = somSelf->GetCMSession(ev);
  329.  
  330.         CMSetMetaHandler(cmSession,
  331.                         (CMGlobalName)CMTargetHandlersTypeName,
  332.                         targetContainerMetahandler);
  333.  
  334.         _fCMContainer = CMOpenNewContainer(cmSession,
  335.                                         _fHandlers,
  336.                                         (CMGlobalName) kODBentoFileTypeName,
  337.                                         (CMContainerUseMode) (kCMWriting),
  338.                                         1, kCMDefaultEndian);
  339.         if (_fCMContainer == kODNULL)
  340.             THROW(kODErrCannotCreateContainer);
  341.     }
  342.  
  343.     return somSelf;
  344. }
  345.  
  346. //------------------------------------------------------------------------------
  347. // ODFileContainer: Open
  348. //------------------------------------------------------------------------------
  349.  
  350. SOM_Scope ODContainer*  SOMLINK ODFileContainerOpen(ODFileContainer *somSelf, Environment *ev)
  351. {
  352.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  353.     ODFileContainerMethodDebug("ODFileContainer","Open");
  354.  
  355.     SOM_CATCH return somSelf;
  356.  
  357.     if (_fCMContainer == kODNULL) {
  358.     
  359.         somSelf->SetModDate(ev, _fPlatformFile->GetFileModDate());
  360.  
  361.         CMSession cmSession = somSelf->GetCMSession(ev);
  362.         
  363.         CMSetMetaHandler(cmSession,
  364.                         (CMGlobalName)CMTargetHandlersTypeName,
  365.                         targetContainerMetahandler);
  366.                         
  367.         _fCMContainer = CMOpenContainer(cmSession,
  368.                                         _fHandlers,
  369.                                         (CMGlobalName) kODBentoFileTypeName,
  370.                                         (CMContainerUseMode) kCMReuseFreeSpace);
  371.         if (_fCMContainer == kODNULL)
  372.             THROW(kODErrCannotOpenContainer);
  373.     }
  374.  
  375.     return somSelf;
  376. }
  377.  
  378. //------------------------------------------------------------------------------
  379. // ODFileContainer: Close
  380. //------------------------------------------------------------------------------
  381.  
  382. SOM_Scope ODContainer*  SOMLINK ODFileContainerClose(ODFileContainer *somSelf, Environment *ev)
  383. {
  384.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  385.     ODFileContainerMethodDebug("ODFileContainer","Close");
  386.  
  387.     SOM_CATCH return somSelf;
  388.  
  389.     if (_fCMContainer != kODNULL) {
  390.         SOM_TRY
  391.             if (somSelf->GetDirtyFlag(ev) != kODFalse) {
  392.                 CMObject    currObj, nextObj;
  393.                 CMProperty    embedProp;
  394.                 CMType        embedType;
  395.                 CMValue        currValue;
  396.                 CMSize        valueSize;
  397.     
  398.                 embedProp = CMRegisterProperty(_fCMContainer, kODPropVersionList);
  399.                 currObj = CMGetNextObjectWithProperty(_fCMContainer, kODNULL, embedProp);
  400.                 CMKeepObject(currObj);
  401.                 embedProp = CMRegisterProperty(_fCMContainer, kODEmbeddedContainerProperty); // "OpenDoc:EmbeddedContainer"
  402.                 embedType = CMRegisterType(_fCMContainer, kODEmbeddedContainerType); // "OpenDoc:EmbeddedContainerType"
  403.                 currObj = CMGetNextObjectWithProperty(_fCMContainer, kODNULL, embedProp);
  404.                 while (currObj) {
  405.                     nextObj = CMGetNextObjectWithProperty(_fCMContainer, currObj, embedProp);
  406.                     currValue = CMUseValue(currObj, embedProp, embedType);
  407.                     if (currValue) {
  408.                         valueSize =  CMGetValueSize(currValue);
  409.                         CMReleaseValue(currValue);
  410.                         if (valueSize)    /* no need to keep it unless length is not zero */
  411.                             CMKeepObject(currObj);
  412.                     } 
  413.                     currObj = nextObj;
  414.                 };
  415.                 CMCloseContainer(_fCMContainer);
  416. #if ODDebug_ODFileContainer
  417. somPrintf("FileContainer Close: Close\n");
  418. #endif
  419.             }
  420.             else {
  421.                 CMAbortContainer(_fCMContainer);
  422. #if ODDebug_ODFileContainer
  423. somPrintf("FileContainer Close: Abort\n");
  424. #endif
  425.             }
  426.             _fPlatformFile->SetFileModDate(somSelf->GetModDate(ev));
  427.         SOM_CATCH_ALL
  428.             if (ErrorCode() == kODErrBentoErr)
  429.                 SetErrorCode(kODErrFatalContainerError);
  430.         SOM_ENDTRY
  431.         _fCMContainer = kODNULL;
  432.     }
  433.     
  434.     return ODFileContainer_parent_ODBentoContainer_Close(somSelf, ev);
  435. }
  436.  
  437. //------------------------------------------------------------------------------
  438. // ODFileContainer: Purge
  439. //------------------------------------------------------------------------------
  440.  
  441. SOM_Scope ODSize  SOMLINK ODFileContainerPurge(ODFileContainer *somSelf, Environment *ev,
  442.         ODSize size)
  443. {
  444.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  445.     ODFileContainerMethodDebug("ODFileContainer","Purge");
  446.  
  447.     ODSize freed = 0;    ODVolatile(freed);
  448.  
  449.     SOM_TRY
  450.          freed = parent_Purge(somSelf, ev, size);
  451.     SOM_CATCH_ALL
  452.         WARN("Error %ld trying to purge in ODFileContainerPurge",ErrorCode());
  453.         SetErrorCode(kODNoError);        // dh - Eat the exception; Purge should not 
  454.                                         // propagate it because clients function
  455.                                         // fine whether memory was purged or not.
  456.                                         // Also, don't return 0 if an exception
  457.                                         // was thrown. Initialized counter should
  458.                                         // suffice to give correct return value.
  459.     SOM_ENDTRY
  460.     
  461.     return freed;
  462. }
  463.  
  464. //------------------------------------------------------------------------------
  465. // ODFileContainer: GetCMContainer
  466. //------------------------------------------------------------------------------
  467.  
  468. SOM_Scope CMContainer  SOMLINK ODFileContainerGetCMContainer(ODFileContainer *somSelf, Environment *ev)
  469. {
  470.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  471.     ODFileContainerMethodDebug("ODFileContainer","GetCMContainer");
  472.  
  473.     return _fCMContainer;
  474. }
  475.  
  476. //------------------------------------------------------------------------------
  477. // ODFileContainer: GetHandlers
  478. //------------------------------------------------------------------------------
  479.  
  480. SOM_Scope ODBentoHandlers*  SOMLINK ODFileContainerGetHandlers(ODFileContainer *somSelf, Environment *ev)
  481. {
  482.     ODFileContainerData *somThis = ODFileContainerGetData(somSelf);
  483.     ODFileContainerMethodDebug("ODFileContainer","GetHandlers");
  484.  
  485.     return _fHandlers;
  486. }
  487.  
  488.